⓪ IMPLEMENTATION MODULE MOSCtrl; (* V#0193 *)⓪ (*$Y+,N+,C+,L-,R-,M-*)⓪ ⓪ (*⓪"22.07.87: Bei Terminierung des gesamten MOS-Prozesses werden alle noch⓪,aktiven Modlevels abgebaut mit jew. Termprocess-Aufruf.⓪"30.08.87: ModLevel wird bei Push/PopPDB verändert. Bei unterstem ModLevel⓪,ist der Wert = 1.⓪"01.10.88: PopPDB wird bei Ende des untersten Prozesse aufgerufen, damit⓪,f. residente Prgs ModLevel dann auf Null steht.⓪"23.10.88: GetPDB liefert ggf. NIL (siehe Def-Text); Removal-Behandlung neu;⓪,Term-Handler wird bei residenten Programmen erst beim Freigeben⓪,ausgelinkt.⓪"15.01.89: PushPDB aktualisiert ggf. BaseProcess und ActMosProcess, da bei⓪.ACCs sonst Unsinn drin stünde.⓪"26.07.89: 408-Vektor wird auch bei residenten Prgs bei Prozeßende ausgelinkt.⓪"04.08.89: 408-Vektor wird mit XBRA ('MM2T') eingelinkt.⓪"16.08.89: Kein infinite Loop, wenn Runtime-Error bei Removal-Calls⓪"20.11.89: Process-ID wird bei TOS 1.0 wieder korrekt ermittelt - MM2 läuft⓪,nun wieder mit TOS 1.0⓪"21.11.90: Term-Handler: Wird bei ACCs nicht installiert, dafür aber nach⓪,Aushängung beim erneuten PushPDB (damit's mit ModLoad klappt);⓪,wenn während der Terminierung wieder Pterm aufgerufen wird, wird⓪,weitergemacht, als sei nix gewesen (die restlichen Term-Handler⓪,werden trotzdem aufgerufen usw).⓪,-nicht getestet!-⓪"25.11.90: Term-Handler: Wenn ein Modul mit TermProcess(0) zurückkehrt, wird⓪,der vorherige ExitCode/termState nicht verändert.⓪"08.12.90: Term-Handler: Der SSP wird nicht mehr aus Prozeß-Daten ermittelt⓪-(denn das Format könnte sich ja mal ändern), sondern wird auf⓪-den Startwert vom Prgstart zurückgesetzt.⓪"05.07.91: Term-Handler: ExitCode-Position wird gesucht, damit's auch mit⓪-KAOS klappt.⓪"03.02.92: 408-Vektor wird wg. MiNT per Bios-Funktion gesetzt.⓪"14.02.92: Wenn MiNT installiert, keine ExitCode-Positionssuche und Term-Hdlr⓪,läuft als Subroutine statt ein 2. Pterm am Ende zu machen.⓪"17.02.92: Wenn MiNT installiert, wird Term-Handler bei jedem neuen Prozeß⓪,in SetProcessState neu installiert. Achtung: bisher wird jedoch⓪,der alte Vektor vom Base-Prozeß jedesmal weiterhin gechained,⓪,obwohl MiNT eigentlich für den neuen Prozeß keine anderen Term-Hdlr⓪,mehr drin hat -> 'vSave' in der XBRA-Struktur müßte in PushPDB⓪,gestacked werden und jedesmal in SetProcessState neu gesetzt werden!⓪"19.02.92: Nun wird bei neuem Prozeß unabh. v. MiNT geprüft, ob der Term-Hdler⓪,noch in der etv_term-Kette installiert ist und ggf. neu installiert;⓪,Auf 408-Vektor wird wieder direkt statt über BIOS zugegriffen.⓪,Leider darf die Exitcode-Suche weiterhin nicht unter MiNT erfolgen,⓪,weil der nächste Supexec-Aufruf nach Pterm() zum Terminate führt.⓪"08.01.94: Mag!X-Anpassung (v. Dirk Steins): Ebenfalls keine Exitcode-Suche⓪"17.01.94: Neues Termination-Handling: 'PrgCtrl.TermProcess' führt bereits die⓪,Term-Handler vor Pterm() aus. Stellen wir im etv_term-Handler fest,⓪,daß noch nicht alles abgemeldet wurde, versuchen wir nicht mehr,⓪,den Exitcode zu korrigieren, denn das Abbrechen des Programms per⓪,Pterm() ist nicht mehr als "saubere" Methode erlaubt.⓪,Der etv_term-Handler wird am Ende immer per Pterm verlassen, auch⓪,bei MiNT/Magix.⓪"08.02.94: Korrektur seit 17.01.94: Falls wir, z.B. durch im Tochterprozeß⓪,noch installiertem GEMError, einen fremden Prozeß beenden, führen⓪,wir natürlich nicht die eigenen Term-Handler aus sondern rufen⓪,Pterm sofort auf.⓪"03.06.94: Noch ein Versuch wg. Problemen, falls ein Prg trotzdem GEMDOS-Pterm⓪,direkt aufruft und MetaDOS o.a. Prgs installiert sind, die im⓪,GEMDOS-Trap hängen und während des Pterm-Handlings mit aufgerufen⓪,werden und es nicht mögen, wenn dann der SSP auf dem fixen Pterm-⓪,Stack bereits steht: Vor Aufruf der Exit-Procs wird der SSP auf⓪,den Programm-USP gesetzt und der USP 512 Byte darunter. Am Ende,⓪,wenn die Exit-Procs ausgeführt wurden, wird wieder der alte SSP⓪,zurückgesetzt, damit es hoffentlich weiter mit rekursiven⓪,Pterms, wie bei Magix möglich, klappt.⓪"24.06.94: Falls ModCtrl BaseResident auf TRUE gesetzt hat und wir den⓪,Basisprozeß beenden, wird am Ende Ptermres statt Pterm aufgerufen.⓪ *)⓪ ⓪ FROM SYSTEM IMPORT ASSEMBLER, ADR, WORD, ADDRESS, TSIZE, LONGWORD, BYTE;⓪ ⓪ FROM MOSGlobals IMPORT MemArea;⓪ ⓪ (*⓪"FROM CookieJar IMPORT GetCookie;⓪ *)⓪ ⓪ (* ! Storage darf nicht importiert werden ! *)⓪ ⓪ ⓪ CONST layout = 4;⓪ ⓪&(*⓪'* Die folg. Konstante legt fest, wie viel Sicherheitsbereich der SSP⓪'* erhalten soll - gleich darunter wird der USP gelegt.⓪'*)⓪&SupervisorStackAmount = 512;⓪&⓪&(*⓪'* Ist die folg Konstanten TRUE, wird bei MiNT & Mag!X am Ende der⓪'* Prozeßterminierung im etv_term-Handler nicht erneut Pterm()⓪'* aufgerufen, sondern ein RTS ausgeführt. Das klappt auch, ist⓪'* aber z.Zt. offenbar überflüssig, da das Verfahren des wiederholten⓪'* Pterm-Aufrufs genausogut in allen Situationen zu klappen scheint.⓪'*)⓪&MiNTaware = FALSE;⓪ ⓪ VAR termVectorInstalled: BOOLEAN;⓪$TOSHdr: LONGWORD;⓪$(*$?MiNTaware:⓪&MagXavail, MiNTavail: BOOLEAN;⓪$*)⓪ ⓪ VAR PtermSSP, mySSP, myUSP: LONGCARD;⓪$didPterm: BYTE;⓪$makeResident: BYTE; (* wird gesetzt, falls InstallModule aufgerufen *)⓪8(* wurde, um dann Ptermres() aufzurufen *)⓪ ⓪ VAR rem408carrier: RemovalEntry;⓪ ⓪ (*⓪ VAR LastSR : WORD;⓪ ⓪ PROCEDURE DisableIR;⓪"BEGIN⓪$ASSEMBLER⓪(PEA upro(PC)⓪(MOVE #38,-(A7)⓪(TRAP #14⓪(ADDQ.L #6,A7⓪(RTS⓪"upro MOVE SR,LastSR⓪(ORI #$0700,SR⓪$END⓪"END DisableIR;⓪ ⓪ PROCEDURE EnableIR;⓪"BEGIN⓪$ASSEMBLER⓪(PEA upro(PC)⓪(MOVE #38,-(A7)⓪(TRAP #14⓪(ADDQ.L #6,A7⓪(RTS⓪"upro MOVE LastSR,SR⓪$END⓪"END EnableIR;⓪ *)⓪ ⓪ PROCEDURE GetPDB ( VAR pdbp : PtrPDB; VAR p: ADDRESS );⓪"BEGIN⓪$ASSEMBLER⓪(MOVE.L ProcessID,A1⓪(MOVE.L (A1),D1 ; D1: akt. Prozeß⓪(MOVE.L -(A3),A0⓪(MOVE.L D1,(A0)⓪(MOVE.L -(A3),A0⓪(TST BaseIsAccessory ; ist Programm ein ACC ?⓪(BEQ notAcc⓪(CMPI #1,ModLevel ; und ist Acc-Prozeß aktiv?⓪(BEQ mos ; -> dann wird PDB geliefert⓪¬Acc⓪(CMP.L ActMOSProcess,D1 ; Akt. Prozeß gleich letztem MOS-Prozeß ?⓪(BEQ mos⓪(TST ModLevel ; oder kein MOS-Prozeß mehr aktiv ?⓪(BEQ mos⓪(CLR.L (A0) ; nein -> pdbp:= NIL⓪(RTS⓪&mos⓪(MOVE.L ActPDB,(A0)⓪$END⓪"END GetPDB;⓪ ⓪ FORWARD HdlTerm;⓪ ⓪ PROCEDURE LookTermHdlr;⓪"BEGIN⓪$ASSEMBLER⓪(; Term-Handler suchen⓪(MOVE SR,D2⓪(ORI #$0700,SR⓪(LEA HdlTerm,A2⓪(ADDA.W #12,A2⓪(LEA $408,A0 ; A0: Vektoradr.⓪%l: MOVE.L (A0),A1⓪(CMPA.L A2,A1 ; 'entry' gefunden?⓪(BEQ f⓪(CMPI.L #$58425241,-12(A1) ; Ist dies ein XBRA-Eintrag?⓪(BNE n ; Nein -> entry hier trotzdem austragen⓪(LEA -4(A1),A0 ; Vorige Vektoradr. nach A0⓪(BRA l⓪%n: MOVE.L A2,A1⓪%f:⓪$END⓪"END LookTermHdlr;⓪ ⓪ PROCEDURE LinkOut408;⓪"BEGIN⓪$ASSEMBLER⓪(CLR.L -(A7)⓪(MOVE #$20,-(A7) ; Super()⓪(TRAP #1⓪(MOVE.L D0,2(A7)⓪(⓪(; Term-Handler auslinken⓪(JSR LookTermHdlr⓪(MOVE.L -4(A1),(A0) ; Entry.old eintragen⓪(CLR.W termVectorInstalled⓪(MOVE D2,SR⓪(⓪(TRAP #1⓪(ADDQ.L #6,A7⓪$END⓪"END LinkOut408;⓪ ⓪ PROCEDURE PushPDB ( pdb: PtrPDB; process: ADDRESS );⓪"BEGIN⓪$ASSEMBLER⓪(; JSR DisableIR⓪(MOVE.L -(A3),D1⓪(BLE.W err⓪(MOVE.L -(A3),D0⓪(BLE.W err⓪(MOVE.L D0,A0⓪(CMPI #layout,PDB.layout(A0)⓪(BNE.W err2⓪ ⓪(MOVE.L D1,ActMOSProcess⓪(MOVE.L PDB.basePageAddr(A0),A2⓪(LEA ActPDB,A1⓪(MOVE.L (A1),PDB.prev(A0)⓪(BNE notBase⓪ ⓪(; *** unterster PDB wird init. ***⓪ ⓪(MOVE.L A2,BaseProcess⓪(MOVE.L A2,ActMOSProcess⓪(TST.L $24(A2)⓪(SEQ D0⓪(ANDI #1,D0⓪(MOVE D0,BaseIsAccessory⓪(MOVE.W PDB.flags(A0),D0⓪(ANDI #3,D0⓪(MOVE D0,RealMode⓪ ⓪((*$?MiNTaware:⓪*MOVEM.L A0-A2,-(A7)⓪*⓪*; Ist MiNT installiert?⓪*MOVE.L #$4D694E54,(A3)+⓪*SUBQ.L #4,A7⓪*MOVE.L A7,(A3)+⓪*JSR GetCookie⓪*ADDQ.L #4,A7 ; value ist uninteressant⓪*MOVE.W -(A3),MiNTavail⓪"⓪*; Ist Mag!X installiert?⓪*MOVE.L #$4D616758,(A3)+⓪*SUBQ.L #4,A7⓪*MOVE.L A7,(A3)+⓪*JSR GetCookie⓪*ADDQ.L #4,A7 ; value ist uninteressant⓪*MOVE.W -(A3),MagXavail⓪"⓪*MOVEM.L (A7)+,A0-A2⓪(*)⓪ ⓪¬Base⓪(MOVE.L A0,(A1)⓪(LEA HdlTerm,A1 ; alten etv_term-Link retten, da er ggf. in⓪(MOVE.L 8(A1),PDB.prevTermHdlr(A0) ; SetProcessState veränd. wird.⓪(MOVE.W #2,PDB.termState(A0)⓪(CLR ExitCode⓪(ADDQ.W #1,ModLevel⓪ ⓪(; Da ACCs nie terminieren, braucht auch kein Term-Vektor installiert⓪(; werden. Ansonsten muß er immer so bald wie möglich installiert werden.⓪(; Dies ist der Fall beim 1. PushPDB-Aufruf in normalen Prgs und bei⓪(; einem Prozeß-Aufruf innerhalb von ACCs. Die Deinstallation muß auf⓪(; dem selben Level erfolgen. Macht sich z.B. ein Prg resident, muß⓪(; der Term-Vektor raus, aber wenn das res. Prg (z.B. ModLoad) dann⓪(; wieder einen Prozeß startet, muß der Term-Vektor wieder rein.⓪(TST.L $24(A2)⓪(BEQ noTermInstall ; bei ACC-Prozeß keinen Term-Vektor installieren⓪(TST.W termVectorInstalled⓪(BNE noTermInstall ; ansonsten installieren, wenn nicht schon getan⓪ ⓪(CLR.L -(A7)⓪(MOVE #$20,-(A7) ; Super()⓪(TRAP #1⓪(MOVE.L D0,2(A7)⓪(⓪(; Pterm-Handler installieren⓪(LEA HdlTerm,A1⓪(ADDA.W #12,A1⓪(LEA $408,A0 ; A0: Vektoradr.⓪(MOVE.L (A0),-4(A1) ; alten Vektor retten (in XBRA-Struktur)⓪(MOVE.L A1,(A0)⓪(⓪(TRAP #1 ; Super() - zurück in Usermode⓪(ADDQ.L #6,A7⓪(⓪(; Catcher installieren, der beim Removal den etv_term wieder aushängt⓪(LEA rem408carrier,A0⓪(MOVE.L #LinkOut408,RemovalEntry.call(A0)⓪(MOVEQ #0,D0⓪(MOVE.L D0,RemovalEntry.wsp.bottom(A0)⓪(MOVE.L D0,RemovalEntry.wsp.length(A0)⓪(LEA RemovalRoot,A2 ; A2: root⓪(MOVE.L A2,RemovalEntry.next(A0)⓪(MOVE.L RemovalEntry.prev(A2),A1 ; A1: root.prev⓪(MOVE.L A1,RemovalEntry.prev(A0)⓪(MOVE.L A0,RemovalEntry.next(A1)⓪(MOVE.L A0,RemovalEntry.prev(A2)⓪(⓪(MOVE #1,termVectorInstalled⓪(⓪&noTermInstall:⓪(; JMP EnableIR⓪(RTS⓪ ⓪&err2⓪(; JSR EnableIR⓪(TRAP #6⓪(DC.W -16 ; internal fault⓪(RTS⓪&err⓪(; JSR EnableIR⓪(TRAP #6⓪(DC.W -14 ; illegal call⓪$END⓪"END PushPDB;⓪ ⓪ PROCEDURE PopPDB;⓪"BEGIN⓪$ASSEMBLER⓪(; JSR DisableIR⓪(LEA ActPDB,A1⓪(MOVE.L (A1),D0⓪(BEQ err⓪(MOVE.L D0,A0⓪(MOVE.L PDB.prev(A0),(A1)⓪(LEA HdlTerm,A1 ; alten etv_term-Link restaurieren⓪(MOVE.L PDB.prevTermHdlr(A0),8(A1)⓪(MOVE.L ProcessID,A0⓪(MOVE.L (A0),ActMOSProcess⓪(SUBQ.W #1,ModLevel⓪(BRA ok⓪&err⓪(TRAP #6⓪(DC.W -14 ; illegal call⓪&ok⓪(; JSR EnableIR⓪$END⓪"END PopPDB;⓪ ⓪ PROCEDURE SetProcessState ( state: CARDINAL );⓪"BEGIN⓪$ASSEMBLER⓪(MOVE.W -(A3),D1⓪(MOVE.L ActPDB,D0⓪(BEQ err⓪(MOVE.L D0,A0⓪(MOVE.W D1,PDB.processState(A0)⓪(CMPI #1,D1⓪(BNE notOne⓪(⓪(; neuer Prozeß gestartet⓪(;------------------------⓪(⓪(; zuerst in den Supervisormode⓪(CLR.L -(A7)⓪(MOVE #$20,-(A7)⓪(TRAP #1⓪(MOVE.L D0,2(A7)⓪(⓪(; SSP des Prozesses ermitteln⓪(MOVE.L ActPDB,A0⓪(MOVE.L D0,PDB.initialSSP(A0)⓪(⓪(; Term-Handler suchen⓪(JSR LookTermHdlr ; D2 enth. noch altes SR!⓪(⓪(; wenn TermHdlr noch installiert, ist alles OK⓪(BEQ stillAvail⓪(⓪(; HdlTerm neu installieren⓪(MOVEA.W #$408,A0⓪(LEA HdlTerm,A1⓪(ADDA.W #12,A1⓪(MOVE.L (A0),-4(A1) ; alten Vektor retten (in XBRA-Struktur)⓪(MOVE.L A1,(A0)⓪(⓪&stillAvail:⓪(MOVE D2,SR ; SR von LookTermHdlr zurücksetzen⓪(⓪(; zurück in der Usermode⓪(TRAP #1⓪(ADDQ.L #6,A7⓪(⓪¬One:⓪(RTS⓪(⓪&err:⓪(TRAP #6⓪(DC.W -14 ; illegal call⓪$END⓪"END SetProcessState;⓪ ⓪ ⓪ PROCEDURE CallSub ( subRoutine: PROC; VAR wsp: MemArea );⓪"BEGIN⓪$ASSEMBLER⓪(MOVE.L -(A3),A0 ; ^wsp⓪(MOVE.L -(A3),A1 ; subRoutine⓪(⓪(MOVE.L A3,-(A7) ; A3 retten⓪(MOVE.L A7,D1 ; alten SP laden zum Retten⓪(⓪(MOVE.L MemArea.bottom(A0),D0 ; neuen SP-Bottom⓪(BEQ useOld ; alten SP verwenden⓪(MOVE.L MemArea.length(A0),D2⓪(BEQ useOld ; alten SP verwenden⓪(⓪(CMPI.L #20,D2⓪(BCS noStack ; Stack zu klein⓪(⓪(; neuen SP verwenden⓪(MOVE.L D0,A3⓪(ADD.L D2,D0⓪(MOVE.L D0,A7⓪(⓪&useOld⓪(MOVE.L D1,-(A7) ; alten SP retten⓪(⓪(JSR (A1)⓪(⓪(MOVE.L (A7)+,A7⓪(MOVE.L (A7)+,A3⓪(RTS⓪(⓪&noStack⓪(TRAP #6⓪(DC.W -10 ; out of stack space⓪$END⓪"END CallSub;⓪ ⓪ ⓪ PROCEDURE CallTermProcs;⓪"BEGIN⓪$ASSEMBLER⓪(MOVE.L ActPDB,D0⓪(BEQ listEnd ; Dürfte eigentlich nicht vorkommen⓪(MOVE.L D0,A0⓪(LEA PDB.termProcs(A0),A2⓪ lstLoop MOVE.L (A2),D0⓪(BEQ listEnd⓪(MOVE.L D0,A0 ; A0: POINTER TO ProcField⓪(MOVE.L TermEntry.next(A0),(A2) ; to be called next⓪(MOVE.L TermEntry.call(A0),(A3)+ ; function to be called now⓪(LEA TermEntry.wsp(A0),A1⓪(MOVE.L A1,(A3)+⓪(MOVE.L A2,-(A7)⓪(JSR CallSub ; call term-function⓪(MOVE.L (A7)+,A2⓪(BRA lstLoop⓪ listEnd⓪$END⓪"END CallTermProcs;⓪ ⓪ ⓪ PROCEDURE CallRemoveProcs;⓪"(* alle Catcher in umgekehrter Anmeldereihenfolge aufrufen *)⓪"BEGIN⓪$ASSEMBLER⓪&l LEA RemovalRoot,A2⓪(LEA RemovalEntry.prev(A2),A2⓪(MOVE.L (A2),A1⓪(CMPA.L #RemovalRoot,A1⓪(BEQ end2⓪(MOVE.L RemovalEntry.prev(A1),(A2) ; to be called next⓪(MOVE.L RemovalEntry.call(A1),(A3)+⓪(LEA RemovalEntry.wsp(A1),A0⓪(MOVE.L A0,(A3)+⓪(JSR CallSub⓪(BRA l⓪&end2⓪$END⓪"END CallRemoveProcs;⓪ ⓪ ⓪ PROCEDURE callExitProcs;⓪"BEGIN⓪$ASSEMBLER⓪(JSR CallTermProcs ; Prozeßende mitteilen⓪(MOVE.L ProcessID,A0⓪(MOVE.L (A0),D0⓪(CMP.L BaseProcess,D0 ; wird Basisprozeß beendet ?⓪(BNE noBaseTerm⓪(TST.W BaseResident ; und ist Prg nicht resident ?⓪(BNE noRemove⓪(JSR CallRemoveProcs ; -> Modul-Entfernung mitteilen⓪(BRA doneRemove⓪ noRemove:⓪(ST makeResident⓪ doneRemove:⓪(; Prg terminiert⓪(; **************⓪(CLR.L BaseProcess⓪(CLR.L ActMOSProcess⓪(CLR ModLevel⓪ noBaseTerm:⓪$END⓪"END callExitProcs;⓪ ⓪ PROCEDURE setTermCode;⓪"BEGIN⓪$ASSEMBLER⓪(; Wenn ein Modul in der Deinit-Phase mit Exitcode 0 terminiert,⓪(; ist das kein Fehler.⓪(CMPI.W #2,PDB.processState(A0) ; Init- oder Run-Phase?⓪(BLS termNormal ; ja, dann Exitcode auf jeden Fall nehmen⓪(TST D1 ; Deinit: Exitcode=0?⓪(BEQ noError ; ja, dann alten Exitcode belassen⓪&termNormal:⓪(MOVE D1,ExitCode⓪(MOVE.W PDB.processState(A0),PDB.termState(A0)⓪&noError:⓪$END⓪"END setTermCode;⓪ ⓪ PROCEDURE terminateResident;⓪"BEGIN⓪$ASSEMBLER⓪(; ptermres (topOfStack-basepage, ExitCode)⓪(SF makeResident⓪(MOVE.W ExitCode,-(A7)⓪(MOVE.L ActPDB,A0⓪(MOVE.L PDB.topOfStack(A0),D0⓪(SUB.L PDB.basePageAddr(A0),D0⓪(MOVE.L D0,-(A7)⓪(MOVE #$31,-(A7)⓪(TRAP #1⓪(ADDQ.L #8,A7⓪$END⓪"END terminateResident;⓪ ⓪ PROCEDURE HdlTerm;⓪"BEGIN⓪$ASSEMBLER⓪(ASC 'XBRA' ; XBRA-Kennung⓪(ASC 'MM2T' ; eigene Kennung⓪ save408 DC.L 0 ; old vector⓪ ⓪(; We're now in supervisor mode!⓪(MOVE.L save408(PC),-(A7)⓪ ⓪(MOVE.L ProcessID,A0⓪(MOVE.L (A0),A1⓪(CMPA.L BaseProcess,A1⓪(BEQ term1⓪(CMPA.L ActMOSProcess,A1⓪(BNE.W notThis⓪ ⓪ term1 MOVE.L ActPDB,D0⓪(BEQ.W ende ; nanu?!⓪(MOVE.L D0,A0⓪ ⓪(CMPI.W #4,PDB.processState(A0)⓪(BCC.W term2 ; Prozeß ist bereits vollst. terminiert⓪ ⓪(; *** Prozeßterminierung nachholen ***⓪(⓪(MOVE ExitCode,D1⓪(BNE tellCode ; falls kein ExitCode gesetzt,⓪(MOVEQ #-1,D1 ; -1 setzen (schließlich sollten wir⓪&tellCode: ; hier normalerweise nicht ankommen)⓪(JSR setTermCode⓪(⓪(CMPI.W #3,PDB.processState(A0) ; bereits Deinit-Phase?⓪(BNE firstPterm ; nein: Pterm-SSP merken⓪(TST.B didPterm ; bereits Pterm-SSP ermittelt?⓪(BEQ firstPterm ; nein: Pterm-SSP merken⓪(⓪((*⓪(idee: da am ende eh die bei rekursiven pterms benutzten stacks⓪(verworfen werden, kann gleich immer derselbe stack verwendet⓪(werden, so wie bei A3. allerdings muß ssp immer noch auf eigenen⓪(bereich zeigen (evtl. initialSSP?) und usp/ssp müssen⓪(geprüft werden, ob sie innerhalb des eigenen stacks bereits⓪(liegen und dann immer dieser wert verwendet werden, anstatt⓪(den stack neu auf dem vollbereich zu nutzen.⓪(*)⓪(⓪(MOVE.L mySSP,A7 ; den bereits verwendeten SSP erneut benutzen⓪(BRA noNewSSP⓪(⓪&firstPterm:⓪(MOVE.W #3,PDB.processState(A0) ; nun Deinit-Phase einleiten⓪(MOVE.L A7,PtermSSP⓪(ST didPterm⓪(⓪(; *** SSP & USP setzen ***⓪(; Dabei prüfen, ob der Pterm-SSP evtl. innerhalb unseres Prozeß-Stacks⓪(; liegt (z.B. verwendet MetaDOS bei Pterm den USP als SSP und ruft⓪(; dann selbst etv_term() auf). In diesem Fall wird der SSP weiterver-⓪(; wendet.⓪(CMPA.L PDB.bottomOfStack(A0),A7⓪(BLS notInside⓪(CMPA.L PDB.topOfStack(A0),A7⓪(BLS isInside⓪¬Inside:⓪(MOVE.L PDB.topOfStack(A0),A7 ; new SSP: USP of terminated process⓪&isInside:⓪(MOVE.L A7,mySSP⓪(⓪&noNewSSP:⓪(; *** setup Stack Pointers & enter User Mode ***⓪(MOVE.L PDB.bottomOfStack(A0),A3 ; use stackptrs of terminated process⓪(MOVE.L A7,A1⓪(SUBA.W #SupervisorStackAmount,A1⓪(MOVE.L A1,USP ; set USP to some bytes below SSP⓪(ANDI #$DFFF,SR⓪(⓪(; *** call installed termination procedures ***⓪(; (last of them removes this handler from the etv_term vector)⓪(MOVE.L A0,-(A7) ; save PDB⓪(JSR callExitProcs⓪(MOVE.L (A7)+,A0 ; PDB zurück⓪(⓪(; *** process is terminated, all exit procs have been called ***⓪(MOVE.W #4,PDB.processState(A0) ; process state: finished⓪(⓪(; *** call final 'Pterm' ***⓪(; (get into Superv Mode to restore SSP)⓪(CLR.L -(A7)⓪(MOVE.W #$20,-(A7)⓪(TRAP #1 ; enter Supervisor Mode to reset SSP⓪(MOVE.L PtermSSP,A7 ; reset Pterm-SSP from first Pterm()⓪(TST.B makeResident⓪(BNE doTermRes⓪(; (no need to get back to User Mode)⓪(MOVE ExitCode,-(A7)⓪(MOVE #$4C,-(A7)⓪(TRAP #1⓪(ADDQ.L #6,A7⓪(BRA ende⓪&doTermRes:⓪(JMP terminateResident⓪ ⓪ term2:⓪ ende:⓪ notThis:⓪(; RTS-Wert ist geretteter $408-Vektor⓪$END⓪"END HdlTerm;⓪ ⓪ PROCEDURE Pterm (exitCode: INTEGER);⓪"BEGIN⓪$ASSEMBLER⓪(; Pterm-Behandlung von 'TermProcess' und M2Init aus.⓪(⓪(TST.L ActPDB⓪(BEQ term0 ; nanu?!⓪(⓪(; ist es überhaupt unser eigener Prozeß, den wir hier beenden?⓪(MOVE.L ProcessID,A1⓪(MOVE.L (A1),A1⓪(CMPA.L BaseProcess,A1⓪(BEQ term1⓪(CMPA.L ActMOSProcess,A1⓪(BEQ term1⓪(⓪(; fremden Prozeß beenden -> Pterm() direkt aufrufen.⓪ term0: MOVE -(A3),-(A7)⓪(MOVE #$4C,-(A7)⓪(TRAP #1⓪ ⓪ term1: ; eigenen Prozeß beenden -> vorher eigene Term-Handler aufrufen⓪ ⓪(; first get into User Mode⓪(MOVEQ #1,D0⓪(MOVE.L D0,-(A7)⓪(MOVE #$20,-(A7)⓪(TRAP #1 ; Super (1) - Get Mode⓪(ADDQ.L #1,D0⓪(BNE isUser⓪(ANDI #$DFFF,SR ; enter User Mode⓪&isUser:⓪(ADDQ.L #6,A7⓪(⓪(MOVE -(A3),D1 ; get exitCode⓪(MOVE.L ActPDB,A0⓪ ⓪(JSR setTermCode⓪(⓪(CMPI.W #3,PDB.processState(A0)⓪(BEQ notFirst⓪(MOVE.W #3,PDB.processState(A0) ; nun Deinit-Phase einleiten⓪(SF didPterm⓪¬First:⓪ ⓪(; reload USP, do not change SSP here⓪(MOVE.L PDB.bottomOfStack(A0),A3 ; use stackptrs of terminated process⓪(MOVE.L PDB.topOfStack(A0),A7 ; new USP⓪(⓪(MOVE.L A0,-(A7) ; save PDB⓪(JSR callExitProcs ; may call this Pterm rekursively⓪(MOVE.L (A7)+,A0 ; PDB zurück⓪(MOVE.W #4,PDB.processState(A0)⓪(⓪(; call final 'Pterm'.⓪(TST.B makeResident⓪(BNE doTermRes⓪(; (no need to get back to User Mode)⓪(MOVE ExitCode,-(A7)⓪(MOVE #$4C,-(A7)⓪(TRAP #1⓪(ADDQ.L #6,A7⓪(BRA ende⓪&doTermRes:⓪(JMP terminateResident⓪&ende:⓪$END⓪"END Pterm;⓪ ⓪ BEGIN⓪"ASSEMBLER⓪(; supervisor mode:⓪(CLR.L -(A7)⓪(MOVE #$20,-(A7)⓪(TRAP #1⓪(MOVE.L D0,2(A7)⓪(MOVE.L $4F2,A0 ; ^TOS-Header⓪(MOVE.L 8(A0),TOSHdr ; wg. altem AHDI⓪(; back to user mode:⓪(TRAP #1⓪(ADDQ.L #6,A7⓪(⓪(MOVE.L TOSHdr,A0⓪(CMPI #$0102,2(A0)⓪(BCC a⓪(MOVE $1C(A0),D1⓪(LSR #1,D1 ; PAL-Bit entfernen⓪(CMPI #4,D1 ; Spanisches TOS?⓪(BEQ b⓪(MOVE.L #$602C, ProcessID⓪(BRA e⓪%b: MOVE.L #$873C, ProcessID⓪(BRA e⓪%a: MOVE.L $28(A0),ProcessID⓪%e:⓪(CLR BaseIsAccessory⓪(CLR.L BaseProcess⓪(CLR.W BaseResident⓪(CLR.L ActMOSProcess⓪(CLR.L ActPDB⓪(CLR.W ModLevel⓪(CLR.W termVectorInstalled⓪(SF makeResident⓪(LEA EnvRoot,A0⓪(MOVE.L A0,EnvEntry.prev(A0)⓪(MOVE.L A0,EnvEntry.next(A0)⓪(LEA RemovalRoot,A0⓪(MOVE.L A0,RemovalEntry.next(A0)⓪(MOVE.L A0,RemovalEntry.prev(A0)⓪"END⓪ END MOSCtrl.⓪ ə